/*
 * @Author: 姚潘涛
 * @Date: 2024-10-12 20:48:59
 * @LastEditors: 姚潘涛
 * @LastEditTime: 2024-10-12 20:51:15
 * @Description:
 *
 * Copyright (c) 2024 by pandaman, All Rights Reserved.
 */
#pragma once

#include "opencv2/opencv.hpp"
#include "xict_common/log/log.h"
#include "xict_common/utils/atan.h"
#include <string>
#include <vector>

namespace xict_common {
    namespace utils {
        class ExposureCompensation {
        public:
            /// \brief Compensates for exposure differences between two images.
            /// \details This function compensates for exposure differences
            /// between two input images by adjusting the brightness and
            /// contrast of the images. \param[in] img1 The first input image.
            /// \param[in] img2 The second input image.
            /// \param[out] img1_compensated The compensated version of img1.
            /// \param[out] img2_compensated The compensated version of img2.
            /// \return true if the exposure compensation is successful, false
            /// otherwise.
            bool CompensateExposure(const cv::Mat& img1, const cv::Mat& img2,
                                    cv::Mat& img1_compensated,
                                    cv::Mat& img2_compensated,
                                    const cv::Point2i& offset = cv::Point2i(0,
                                                                            0));

        protected:
            /// \brief Apply the histogram mapping to an input image
            /// \param map Vector of 3 cv::Mat objects representing the mapping
            /// for each channel \param input Input image to be adjusted \return
            /// Adjusted image after applying the histogram mapping

            ///
            /// \brief Apply the histogram mapping to an input image (Pixel
            /// Adjustment) \details This function takes a set of histogram
            /// mappings and applies them to an input image, adjusting the pixel
            /// values in each channel according to the provided mappings.
            /// \param map A vector of 3 cv::Mat objects, each representing the
            /// mapping for one color channel (B, G, R). Each mapping is a 1x256
            /// matrix of float values, where the index represents the input
            /// pixel value, and the stored float value represents the output
            /// pixel value. \param input The input image to be adjusted. Should
            /// be a 3-channel (BGR) image. \return The adjusted image after
            /// applying the histogram mapping. \note The function assumes that
            /// the input image and the mapping have 3 channels and 8-bit depth.
            cv::Mat ApplyHistogramMapping(const std::vector<cv::Mat>& map,
                                          const cv::Mat& input);

            /// \brief Calculate the histogram threshold for noise removal
            /// \details This function computes a threshold value for each
            /// channel of the image histogram. The threshold is used to
            /// identify and remove low-frequency components (noise) in the
            /// histogram. \param na A vector of 3 cv::Mat objects, each
            /// representing the histogram of one color channel (B, G, R). Each
            /// histogram should be a 1x256 matrix of float values, where each
            /// value represents the frequency of a particular intensity level.
            /// \param pixel_num The total number of pixels in the image.
            /// \return A vector of 3 float values, each representing
            /// the calculated threshold for one color channel (B, G, R).
            /// \note The threshold is calculated as the intensity level at
            /// which the cumulative sum of sorted histogram values reaches 5%
            /// of the total pixel count.
            std::vector<float>
            CalculateHistogramThreshold(const std::vector<cv::Mat>& na,
                                        int pixel_num);

            /// \brief Perform Hybrid Histogram Matching on the input images
            /// \details This function implements a hybrid histogram matching
            /// algorithm to map the histogram of a source image to a target
            /// image. It combines global histogram matching with local
            /// adjustments to preserve image details. \param im_tgt The target
            /// image. The histogram of the source image will be matched to this
            /// image. \param im_src The source image. This image's histogram
            /// will be adjusted. \return A vector of 3 cv::Mat objects, each
            /// representing the mapping for one color channel (B, G, R). Each
            /// mapping is a 1x256 matrix of float values, where the index
            /// represents the input pixel value, and the stored float value
            /// represents the output pixel value. \note The function performs
            /// the following steps:
            /// 1. Calculates histograms and cumulative histograms for both
            /// images
            /// 2. Computes an initial mapping based on cumulative histograms
            /// 3. Applies thresholding to remove noise
            /// 4. Performs local adjustments to preserve image details
            /// 5. Smooths the final mapping
            std::vector<cv::Mat>
            PerformHybridHistogramMatching(const cv::Mat& im_tgt,
                                           const cv::Mat& im_src);
        };
    }   // namespace utils
}   // namespace xict_common